package com.zycfc.zsf.boot.util.text;

import com.zycfc.zsf.boot.util.number.*;
import java.lang.management.*;
import java.net.*;
import java.util.*;
import org.apache.commons.lang3.*;
import org.slf4j.*;

public class SnowflakeKeyWorker
{
    private static final Logger log;
    private static final long TWEPOCH = 12888349746579L;
    private static final long WORKERIDBITS = 5L;
    private static final long DATACENTERIDBITS = 5L;
    private static final long SEQUENCEBITS = 12L;
    private static final long WORKERIDSHIFT = 12L;
    private static final long DATACENTERIDSHIFT = 17L;
    private static final long TIMESTAMPLEFTSHIFT = 22L;
    private static final long SEQUENCEMASK = 4095L;
    private static long lastTimestamp;
    private long sequence;
    private long workerId;
    private static long workerMask;
    private long processId;
    private static long processMask;
    private static SnowflakeKeyWorker keyWorker;
    
    public static synchronized String nextId() {
        final String snowId = String.valueOf(SnowflakeKeyWorker.keyWorker.getNextId());
        final String randId = String.valueOf(RandomUtils.nextInt(1000, 9999));
        return snowId + randId;
    }
    
    @Deprecated
    public static synchronized long nextLongId() {
        return SnowflakeKeyWorker.keyWorker.getNextId();
    }
    
    private SnowflakeKeyWorker() {
        this.sequence = 0L;
        this.workerId = 1L;
        this.processId = 1L;
        this.workerId = this.getMachineNum();
        final RuntimeMXBean runtimeMXBean = ManagementFactory.getRuntimeMXBean();
        this.processId = Long.valueOf(runtimeMXBean.getName().split("@")[0]);
        this.workerId &= SnowflakeKeyWorker.workerMask;
        this.processId &= SnowflakeKeyWorker.processMask;
    }
    
    private synchronized long getNextId() {
        long timestamp = this.timeGen();
        if (timestamp < SnowflakeKeyWorker.lastTimestamp) {
            try {
                throw new Exception("Clock moved backwards.  Refusing to generate id for " + (SnowflakeKeyWorker.lastTimestamp - timestamp) + " milliseconds");
            }
            catch (Exception e) {
                SnowflakeKeyWorker.log.error("\u65f6\u95f4\u6233\u5c0f\u4e8e\u4e0a\u6b21\u65f6\u95f4\u6233", (Throwable)e);
            }
        }
        if (SnowflakeKeyWorker.lastTimestamp == timestamp) {
            this.sequence = (this.sequence + 1L & 0xFFFL);
            if (this.sequence == 0L) {
                timestamp = this.tilNextMillis(SnowflakeKeyWorker.lastTimestamp);
            }
        }
        else {
            this.sequence = 0L;
        }
        SnowflakeKeyWorker.lastTimestamp = timestamp;
        return timestamp - 12888349746579L << 22 | this.processId << 17 | this.workerId << 12 | this.sequence;
    }
    
    private long tilNextMillis(final long lastTimestamp) {
        long timestamp;
        for (timestamp = this.timeGen(); timestamp <= lastTimestamp; timestamp = this.timeGen()) {}
        return timestamp;
    }
    
    private long timeGen() {
        return System.currentTimeMillis();
    }
    
    private long getMachineNum() {
        final StringBuilder sb = new StringBuilder();
        Enumeration<NetworkInterface> e = null;
        try {
            e = NetworkInterface.getNetworkInterfaces();
        }
        catch (SocketException e2) {
            SnowflakeKeyWorker.log.error("\u83b7\u53d6\u673a\u5668\u7f16\u7801\u5f02\u5e38", (Throwable)e2);
        }
        while (e.hasMoreElements()) {
            final NetworkInterface ni = e.nextElement();
            sb.append(ni.toString());
        }
        final long machinePiece = sb.toString().hashCode();
        return machinePiece;
    }
    
    public static void main(final String[] args) {
        for (int i = 0; i < 100; ++i) {
            System.out.println(nextLongId());
            System.out.println(nextId());
        }
    }
    
    private static String long2BinaryStr(final Long l) {
        return StringUtils.leftPad(Long.toBinaryString(l), 64, '0');
    }
    
    static {
        log = LoggerFactory.getLogger((Class)SnowflakeKeyWorker.class);
        SnowflakeKeyWorker.lastTimestamp = -1L;
        SnowflakeKeyWorker.workerMask = 31L;
        SnowflakeKeyWorker.processMask = 31L;
        SnowflakeKeyWorker.keyWorker = null;
        SnowflakeKeyWorker.keyWorker = new SnowflakeKeyWorker();
    }
}
